#include "NUC1xx.h"
#include "DrvGPIO.h"
#include "DrvTimer.h"

#include "hal_nrf.h"

#define SPI0_CSN_HIGH()	DrvGPIO_SetBit(E_GPC, 0)
#define SPI0_CSN_LOW()	DrvGPIO_ClrBit(E_GPC, 0)

#define SPI0_CLK_HIGH()	DrvGPIO_SetBit(E_GPC, 1)
#define SPI0_CLK_LOW()	DrvGPIO_ClrBit(E_GPC, 1)

#define SPI0_MISO()	DrvGPIO_GetBit(E_GPC, 2)

#define SPI0_MOSI_HIGH()	DrvGPIO_SetBit(E_GPC, 3)
#define SPI0_MOSI_LOW()		DrvGPIO_ClrBit(E_GPC, 3)

#define SPI0_CE_HIGH()	DrvGPIO_SetBit(E_GPC, 4)
#define SPI0_CE_LOW()	DrvGPIO_ClrBit(E_GPC, 4)


static void (*hal_nrf_intproc)(void);

uint8_t SPI_RW(uint8_t u8WData)
{
	uint8_t u8bit;
	uint8_t u8Read = 0x00;

	for(u8bit = 0x80; u8bit != 0; u8bit = u8bit>>1)
	{
		if(u8bit & u8WData)
		{
			SPI0_MOSI_HIGH();
		}
		else
		{
			SPI0_MOSI_LOW();
		}


		SPI0_CLK_HIGH();

		if(SPI0_MISO() == 0x01)
		{
			u8Read |= u8bit;
		}


		SPI0_CLK_LOW();
	}

	return u8Read;
}

/*
uint8_t Nrf24l01_Write(uint8_t u8Cmd, uint8_t *pu8Buf, uint8_t u8Len)
{
	uint8_t u8Status;
	uint8_t u8i;

	SPI0_CSN_LOW();

	u8Status = SPI_RW(u8Cmd);
	for(u8i = 0; u8i<u8Len; u8i++)
	{
		SPI_RW(pu8Buf[u8i]);
	}
	SPI0_CSN_HIGH();
	return u8Status;
}

uint8_t Nrf24l01_Read(uint8_t u8Cmd, uint8_t *pu8Buf, uint8_t u8Len)
{
	uint8_t u8Status;
	uint8_t u8i;

	SPI0_CSN_LOW();
	DrvTIMER_Delay(E_TMR0, 1);
	u8Status = SPI_RW(u8Cmd);
	for(u8i = 0; u8i<u8Len; u8i++)
	{
		pu8Buf[u8i] = SPI_RW(0xFF);
	}

	SPI0_CSN_HIGH();
	return u8Status;
}
*/



void gpio_intproc(uint32_t u32GPCStatus, uint32_t u32GPDStatus, uint32_t u32GPEStatus)
{
	//nrf2401 use GPC5 int
	if(u32GPCStatus & (0x01<<5))
	{
		if(hal_nrf_intproc != NULL)
		{
			hal_nrf_intproc();
		}
	}
}

void hal_nrf_init(NRF_IRQ_CB pfn)
{	
	//CFG CSN
	DrvGPIO_Open(E_GPC, 0, E_IO_OUTPUT);
	//CFG CLK
	DrvGPIO_Open(E_GPC, 1, E_IO_OUTPUT);
	//CFG MISO
	DrvGPIO_Open(E_GPC, 2, E_IO_INPUT);
	//CFG MOSI
	DrvGPIO_Open(E_GPC, 3, E_IO_OUTPUT);
	//CFG CE
	DrvGPIO_Open(E_GPC, 4, E_IO_OUTPUT);
	//CFG IRQ
	hal_nrf_intproc = pfn;
	DrvGPIO_SetIntCallback(NULL, gpio_intproc);
	DrvGPIO_EnableInt(E_GPC, 5, E_IO_FALLING, E_MODE_EDGE);

	SPI0_CE_LOW();
	SPI0_CSN_HIGH();
	SPI0_CLK_LOW();


	
}

//porting for nrf

uint8_t hal_nrf_read_reg(uint8_t reg)
{
uint8_t temp;
  SPI0_CSN_LOW();
  SPI_RW(reg);
  temp = SPI_RW(0);
  SPI0_CSN_HIGH();

  return temp;
}

uint8_t hal_nrf_write_reg(uint8_t reg, uint8_t value)
{
  uint8_t retval;
  SPI0_CSN_LOW();
  if(reg < WRITE_REG)   // i.e. this is a register access
  {
    retval = SPI_RW(WRITE_REG + reg);
    SPI_RW(value);
  }
  else            // single byte cmd OR future command/register access
  {
    if(!(reg == FLUSH_TX) && !(reg == FLUSH_RX) && !(reg == REUSE_TX_PL) && !(reg == NOP))
    {
      retval = SPI_RW(reg);
      SPI_RW(value);
    }
    else          // single byte L01 command
    {
      retval = SPI_RW(reg);
    }
  }
  SPI0_CSN_HIGH();

  return retval;
}

uint16_t hal_nrf_read_multibyte_reg(uint8_t reg, uint8_t *pbuf)
{
uint8_t ctr, length;
  switch(reg)
  {
    case HAL_NRF_PIPE0:
    case HAL_NRF_PIPE1:
    case HAL_NRF_TX:
      length = ctr = hal_nrf_get_address_width();
      SPI0_CSN_LOW();
      SPI_RW(RX_ADDR_P0 + reg);
      break;
      
    case HAL_NRF_RX_PLOAD:
      if( (reg = hal_nrf_get_rx_data_source()) < 7)
      {
        length = ctr = hal_nrf_read_rx_pl_w();

        SPI0_CSN_LOW();
        SPI_RW(RD_RX_PLOAD);
      }
      else
      {
       ctr = length = 0;
      }
      break;

    default:
      ctr = length = 0;
      break;
  }

  while(ctr--)
  {
    *pbuf++ = SPI_RW(0);
  }

  SPI0_CSN_HIGH();

  return (((uint16_t) reg << 8) | length);
}

void hal_nrf_write_multibyte_reg(uint8_t reg, uint8_t *pbuf, uint8_t length)
{
  switch(reg)
  {
    case HAL_NRF_PIPE0:
    case HAL_NRF_PIPE1:
    case HAL_NRF_TX:
      length = hal_nrf_get_address_width();
      SPI0_CSN_LOW();
      SPI_RW(WRITE_REG + RX_ADDR_P0 + reg);
      break;
      
    case HAL_NRF_TX_PLOAD:
      SPI0_CSN_LOW();
      SPI_RW(WR_TX_PLOAD);
      break;      
    default:
      break;
  }

  while(length--)
  {
    SPI_RW(*pbuf++);
  }

  SPI0_CSN_HIGH();
}

void hal_nrf_ce_plus(void)
{
	SPI0_CE_HIGH();
	clock_wait(1);
	SPI0_CE_LOW();
}


void hal_nrf_write_ack_pload(uint8_t pipe, uint8_t *tx_pload, uint8_t length)
{
  SPI0_CSN_LOW();

  SPI_RW(WR_ACK_PLOAD | pipe);
  while(length--)
  {
    hal_nrf_rw(*tx_pload++);
  }

  SPI0_CSN_HIGH();
}

uint8_t hal_nrf_read_rx_pl_w()
{
  uint8_t temp;
  
  SPI0_CSN_LOW();

  SPI_RW(RD_RX_PLOAD_W);
  temp = SPI_RW(0);
  SPI0_CSN_HIGH();

  return temp;
}

void hal_nrf_lock_unlock()
{
  SPI0_CSN_LOW();

  SPI_RW(LOCK_UNLOCK);             
  SPI_RW(0x73);

  SPI0_CSN_HIGH();
}


